﻿using Coolzon.UI.Core.Properties;
using Coolzon.UI.Core.XProperty;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using RT = Coolzon.Metadata.Runtime;

namespace Coolzon.UI.Core
{
    public partial class Widget
    {
        private string _xCaption;

        protected bool NeedUpdateLayout = false;
        #region XProperties

        public string XCaption
        {
            get
            {
                return _xCaption;
            }
            set
            {
                if (!string.Equals(_xCaption, value))
                {
                    _xCaption = value;
                    RaisePropertyChanged("XCaption");
                }
            }
        }

        /// <summary>
        /// 锚点(0,0)-(1,1)
        /// </summary>
        private Point _anchorPoint;

        [XProperty(XPropertyCategory.Script, "AnchorPoint", "锚点")]
        public Point AnchorPoint
        {
            get
            {
                return _anchorPoint;
            }
            set
            {
                _anchorPoint = value;
                RaisePropertyChanged("AnchorPoint");
                this.RenderTransformOrigin = _anchorPoint;
            }
        }

        [XProperty(XPropertyCategory.Script, "Rotate", "旋转度数")]
        public double Rotate
        {
            get
            {
                return (double)GetValue(RotateProperty);
            }
            set
            {
                SetValue(RotateProperty, value);
            }
        }

        /// <summary>
        /// 显示条件，这里定义了显示的表达式，如果表达式为空则显示，不为空返回的值为true显示，false不显示
        /// </summary>
        [Category("脚本")]
        [DisplayName("显示条件")]
        [Description("DisplayCondition")]
        //[Editor(typeof(Editors.StringEditor), typeof(XProperty.XPropertyValueEditor))]
        [XProperty(XPropertyCategory.Script, "DisplayCondition", "显示条件")]
        public string XDisplayCondition
        {
            get
            {
                return (string)GetValue(XDisplayConditionProperty);
            }
            set
            {
                SetValue(XDisplayConditionProperty, value);
            }
        }
        [Category("Layout")]
        [DisplayName("左部距离")]
        [Description("Left")]
        //[Editor(typeof(XProperty.Editors.XDoubleEditor), typeof(XProperty.XPropertyValueEditor))]
        [XProperty(XPropertyCategory.Layout, "Left", "左部距离")]
        public double Left
        {
            get
            {
                return (double)GetValue(XLeftProperty);
            }
            set
            {
                SetValue(XLeftProperty, value);
            }
        }

        [Category("Layout")]
        [DisplayName("上部距离")]
        [Description("Top")]
        //[Editor(typeof(XProperty.Editors.XDoubleEditor), typeof(XProperty.XPropertyValueEditor))]
        [XProperty(XPropertyCategory.Layout, "Top", "上部距离")]
        public double Top
        {
            get
            {
                return (double)GetValue(XTopProperty);
            }
            set
            {
                SetValue(XTopProperty, value);
            }
        }

        //[Category("Layout")]
        //[DisplayName("高度")]
        //[Description("Height")]
        ////[Editor(typeof(XProperty.Editors.XDoubleEditor), typeof(XProperty.XPropertyValueEditor))]
        //[XProperty(XPropertyCategory.Layout, "Height", "高度")]
        //public double XHeight
        //{
        //    get
        //    {
        //        return (double)GetValue(XHeightProperty);
        //    }
        //    set
        //    {
        //        SetValue(XHeightProperty, value);
        //    }
        //}

        //[Category("Layout")]
        //[DisplayName("宽度")]
        //[Description("Width")]
        ////[Editor(typeof(XProperty.Editors.XDoubleEditor), typeof(XProperty.XPropertyValueEditor))]
        //[XProperty(XPropertyCategory.Layout, "Width", "宽度")]
        //public double XWidth
        //{
        //    get
        //    {
        //        return (double)GetValue(XWidthProperty);
        //    }
        //    set
        //    {
        //        SetValue(XWidthProperty, value);
        //    }
        //}

        ///// <summary>
        ///// 背景颜色
        ///// </summary>
        //[Category("Appearance")]
        //[DisplayName("背景颜色")]
        //[Description("Background")]
        ////[Editor(typeof(XProperty.Editors.XBrushEditor), typeof(XProperty.XPropertyValueEditor))]
        //[XProperty(XPropertyCategory.Appearance, "Background", "背景颜色")]
        //public Brush XBackground
        //{
        //    get
        //    {
        //        return (Brush)GetValue(XBackgroundProperty);
        //    }
        //    set
        //    {
        //        SetValue(XBackgroundProperty, value);
        //    }
        //}

        //[Category("Appearance")]
        //[DisplayName("前景颜色")]
        //[Description("Foreground")]
        ////[Editor(typeof(XProperty.Editors.XBrushEditor), typeof(XProperty.XPropertyValueEditor))]
        //[XProperty(XPropertyCategory.Appearance, "Foreground", "前景颜色")]
        //public Brush XForeground
        //{
        //    get
        //    {
        //        return (Brush)GetValue(XForegroundProperty);
        //    }
        //    set
        //    {
        //        SetValue(XForegroundProperty, value);
        //    }
        //}

        /// <summary>
        /// 背景图片
        /// </summary>
        [Category("Brush")]
        [DisplayName("背景图片")]
        [Description("BackgroundImage")]
        //[Editor(typeof(XProperty.Editors.XImageSourceFileEditor), typeof(XProperty.XPropertyValueEditor))]
        [XProperty(XPropertyCategory.Brush, "BackgroundImage", "背景图片", true, true)]
        public ImageSourceFile XBackgroundImage
        {
            get
            {
                return (ImageSourceFile)GetValue(XBackgroundImageProperty);
            }
            set
            {
                SetValue(XBackgroundImageProperty, value);
            }
        }

        /// <summary>
        /// 边框颜色
        /// </summary>
        [Category("Appearance")]
        [DisplayName("边框颜色")]
        [Description("BorderBrush")]
        //[Editor(typeof(XProperty.Editors.XBrushEditor), typeof(XProperty.XPropertyValueEditor))]
        [XProperty(XPropertyCategory.Appearance, "BorderBrush", "边框颜色")]
        public Brush XBorderBrush
        {
            get
            {
                return (Brush)GetValue(XBorderBrushProperty);
            }
            set
            {
                SetValue(XBorderBrushProperty, value);
            }
        }

        ///// <summary>
        ///// 边框大小
        ///// </summary>
        //[Category("Appearance")]
        //[DisplayName("边框大小")]
        //[Description("BorderThickness")]
        ////[Editor(typeof(XProperty.Editors.XThicknessEditor), typeof(XProperty.XPropertyValueEditor))]
        //[XProperty(XPropertyCategory.Appearance, "BorderThickness", "边框大小")]
        //public Thickness XBorderThickness
        //{
        //    get
        //    {
        //        return (Thickness)GetValue(XBorderThicknessProperty);
        //    }
        //    set
        //    {
        //        SetValue(XBorderThicknessProperty, value);
        //    }
        //}

        //[Category("Layout")]
        //[DisplayName("外边距")]
        //[Description("Margin")]
        ////[Editor(typeof(XProperty.Editors.XThicknessEditor), typeof(XProperty.XPropertyValueEditor))]
        //[XProperty(XPropertyCategory.Layout, "Margin", "外边距", true, true)]
        //public Thickness XMargin
        //{
        //    get
        //    {
        //        return (Thickness)GetValue(XMarginProperty);
        //    }
        //    set
        //    {
        //        SetValue(XMarginProperty, value);
        //    }
        //}

        //[Category("Layout")]
        //[DisplayName("内边距")]
        //[Description("Padding")]
        ////[Editor(typeof(XProperty.Editors.XThicknessEditor), typeof(XProperty.XPropertyValueEditor))]
        //[XProperty(XPropertyCategory.Layout, "Padding", "内边距")]
        //public Thickness XPadding
        //{
        //    get
        //    {
        //        return (Thickness)GetValue(XPaddingProperty);
        //    }
        //    set
        //    {
        //        SetValue(XPaddingProperty, value);
        //    }
        //}

        //private bool _isVisible = true;
        ///// <summary>
        ///// 
        ///// </summary>
        //[Category("Appearance")]
        //[DisplayName("是否可见")]
        //[Description("IsVisible")]
        ////[Editor(typeof(XProperty.Editors.XBooleanEditor), typeof(XProperty.XPropertyValueEditor))]
        //[XProperty(XPropertyCategory.Appearance, "IsVisible", "是否可见", true)]
        //public bool XIsVisible
        //{
        //    get
        //    {
        //        return (bool)GetValue(XIsVisibleProperty);
        //    }
        //    set
        //    {
        //        SetValue(XIsVisibleProperty, value);
        //    }
        //}
        #endregion

        #region dependency property

        public static DependencyProperty RotateProperty = DependencyProperty.Register("Rotate",
            typeof(double),
            typeof(Widget),
            new PropertyMetadata(default(double), OnRotatePropertyChangedCallback));

        public static DependencyProperty XDisplayConditionProperty = DependencyProperty.Register("XDisplayCondition",
            typeof(string),
            typeof(Widget),
            new PropertyMetadata(default(string), XDisplayConditionPropertyChangedCallback));

        public static DependencyProperty XLeftProperty = DependencyProperty.Register("XLeft",
            typeof(double),
            typeof(Widget),
            new PropertyMetadata(default(double), XLeftPropertyChangedCallback));

        public static DependencyProperty XTopProperty = DependencyProperty.Register("XTop",
            typeof(double),
            typeof(Widget),
            new PropertyMetadata(default(double), XTopPropertyChangedCallback));

        //public static DependencyProperty XWidthProperty = DependencyProperty.Register("XWidth",
        //    typeof(double),
        //    typeof(Part),
        //    new PropertyMetadata(default(double), XWidthPropertyChangedCallback));

        public static DependencyProperty XHeightProperty = DependencyProperty.Register("XHeight",
            typeof(double),
            typeof(Widget),
            new PropertyMetadata(default(double), XHeightPropertyChangedCallback));

        //public static DependencyProperty XBackgroundProperty = DependencyProperty.Register("XBackground",
        //    typeof(Brush),
        //    typeof(Part),
        //    new PropertyMetadata(null, XPropertyChangedCallback));

        public static DependencyProperty XForegroundProperty = DependencyProperty.Register("XForeground",
            typeof(Brush),
            typeof(Widget),
            new PropertyMetadata(null, XPropertyChangedCallback));

        public static DependencyProperty XBackgroundImageProperty = DependencyProperty.Register("XBackgroundImage",
            typeof(ImageSourceFile),
            typeof(Widget),
            new PropertyMetadata(null, XPropertyChangedCallback));

        public static DependencyProperty ToolbarContentProperty = DependencyProperty.Register("ToolbarContent",
            typeof(object),
            typeof(Widget),
            null);

        public static DependencyProperty XBorderBrushProperty = DependencyProperty.Register("XBorderBrush",
            typeof(Brush),
            typeof(Widget),
            new PropertyMetadata(null, XBorderBrushPropertyChangedCallback));

        public static DependencyProperty XBorderThicknessProperty = DependencyProperty.Register("XBorderThickness",
            typeof(Thickness),
            typeof(Widget),
            new PropertyMetadata(default(Thickness), XBorderThicknessPropertyChangedCallback));

        //public static DependencyProperty XMarginProperty = DependencyProperty.Register("XMargin",
        //    typeof(Thickness),
        //    typeof(Part),
        //    new PropertyMetadata(default(Thickness), XMarginPropertyChangedCallback));

        //public static DependencyProperty XPaddingProperty = DependencyProperty.Register("XPadding",
        //    typeof(Thickness),
        //    typeof(Part),
        //    new PropertyMetadata(default(Thickness), XPaddingPropertyChangedCallback));

        public static DependencyProperty XIsDesignModeProperty = DependencyProperty.Register("XIsDesignMode",
            typeof(bool),
            typeof(Widget),
            new PropertyMetadata(false, XIsDeisgnModePropertyChangedCallback));

        //public static DependencyProperty XIsVisibleProperty = DependencyProperty.Register("XIsVisible",
        //    typeof(bool),
        //    typeof(Part),
        //    new PropertyMetadata(true, XIsVisiblePropertyChangedCallback));
        #endregion

        #region dependencyProperty callback

        private static void OnRotatePropertyChangedCallback(DependencyObject @object, DependencyPropertyChangedEventArgs args)
        {
            Widget part = @object as Widget;
            if(part.RenderTransform == null || part.RenderTransform == MatrixTransform.Identity)
            {
                TransformGroup tfGroup = new TransformGroup();
                part.RenderTransform = tfGroup;

                RotateTransform rtf = new RotateTransform();
                tfGroup.Children.Add(rtf);

                rtf.Angle = (double)args.NewValue;
            }
            else
            {
                TransformGroup tfGroup = part.RenderTransform as TransformGroup;
                for(int index = 0; index < tfGroup.Children.Count; index++)
                {
                    if(tfGroup.Children[index] is RotateTransform)
                    {
                        (tfGroup.Children[index] as RotateTransform).Angle = (double)args.NewValue;
                        return;
                    }
                }
            }
        }

        private static void XDisplayConditionPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Widget part = d as Widget;
            part.RaisePropertyChanged(e.Property.Name);
        }

        private static void XLeftPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Widget part = d as Widget;
            System.Windows.Controls.Canvas.SetLeft(part, (double)e.NewValue);
            part.UpdateSize();
            part.RaisePropertyChanged(e.Property.Name);
        }

        private static void XTopPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Widget part = d as Widget;
            System.Windows.Controls.Canvas.SetTop(part, (double)e.NewValue);
            part.UpdateSize();
            part.RaisePropertyChanged(e.Property.Name);
        }

        private static void XWidthPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Widget part = d as Widget;
            part.Width = (double)e.NewValue;
            part.NeedUpdateLayout = true;
            part.RaisePropertyChanged(e.Property.Name);
            part.Refresh();
        }

        private static void XHeightPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Widget part = d as Widget;
            part.Height = (double)e.NewValue;
            part.NeedUpdateLayout = true;
            part.RaisePropertyChanged(e.Property.Name);
            part.Refresh();
        }

        private static void XPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Widget part = d as Widget;
            part.RaisePropertyChanged(e.Property.Name);
            part.Refresh();
        }

        private static void XBorderBrushPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Widget part = d as Widget;
            part.RaisePropertyChanged(e.Property.Name);
            part.Refresh();
        }
        private static void XBorderThicknessPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Widget part = d as Widget;
            part.RaisePropertyChanged(e.Property.Name);
            part.Refresh();
        }
        //private static void XPaddingPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        //{
        //    Part part = d as Part;
        //    part.RaisePropertyChanged(e.Property.Name);
        //    part.Refresh();
        //}
        private static void XIsDeisgnModePropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Widget part = d as Widget;
            part.RaisePropertyChanged(e.Property.Name);
        }
        private static void OnXVisiblePropertyChangedCallback(DependencyObject @object, DependencyPropertyChangedEventArgs e)
        {
            if ((Visibility)e.NewValue == Visibility.Visible)
            {
                Widget instance = @object as Widget;
                instance.Active(instance.PartContext);
            }
        }
        #endregion

        public static XPropertyDescription XBackground = new XPropertyDescription(typeof(Widget), "Background", "other", "背景颜色", null);
        public static XPropertyDescription XForeground = new XPropertyDescription(typeof(Widget), "Foreground", "other", "前景色", null);
        public static XPropertyDescription XFontSize = new XPropertyDescription(typeof(Widget), "FontSize", "other", "字体大小", null);

        public static XPropertyDescription XWidth = new XPropertyDescription(typeof(Widget), "Width", "other", "宽度", null);
        public static XPropertyDescription XHeight = new XPropertyDescription(typeof(Widget), "Height", "other", "高度", null);

        public static XPropertyDescription XMargin = new XPropertyDescription(typeof(Widget), "Margin", "other", "外部间距", null);
        public static XPropertyDescription XPadding = new XPropertyDescription(typeof(Widget), "Padding", "other", "内部间距", null);
        public static XPropertyDescription XVisibility = new XPropertyDescription(typeof(Widget), "Visibility", "other", "可见性", OnXVisiblePropertyChangedCallback);
        public static XPropertyDescription XBorderThickness = new XPropertyDescription(typeof(Widget), "BorderThickness", "other", "边框大小", null);

        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            if (this.IsLoaded && this._isRestoring == false)
            {
                List<XPropertyDescription> propertyDescriptions = XPropertyDescriptionCache.Instance.Get(this.GetType());
                foreach (var propertyDescription in propertyDescriptions)
                {
                    if (propertyDescription.PropertyChangedCallback != null && string.Equals(propertyDescription.XPropertyAttribute.Name, e.Property.Name))
                    {
                        propertyDescription.PropertyChangedCallback(this, e);
                        break;
                    }
                }
            }
            base.OnPropertyChanged(e);
        }
    }
}
